package com.st.rzs.util;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONObject;

/**
 * Http请求工具类
 */
public class HttpClientUtils {

	protected static Log logger = LogFactory.getLog(HttpClientUtils.class);

	/**
	 * get请求
	 * 
	 * @param url：请求url路径
	 * @param uriVariables：请求参数
	 * @param clazz：返回数据类型
	 * @return
	 */
	public static ResponseModel doGet(String url, Map<String, Object> uriVariables, Class clazz) {
		// 开始处理http请求信息
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		ResponseModel responseModel = new ResponseModel();
		try {
			URIBuilder builder = new URIBuilder(url);
			Set<String> set = uriVariables.keySet();
			for (String key : set) {
				builder.setParameter(key, String.valueOf(uriVariables.get(key)));
			}
			HttpGet httpGet = new HttpGet(builder.build());
			// 设置连接超时时间，单位毫秒。
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000)
					// .setConnectionRequestTimeout(1000) 设置从connect
					// Manager获取Connection
					// 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。
					// .setSocketTimeout(5000) 请求获取数据的超时时间，单位毫秒。
					// 如果访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。
					.build();
			httpGet.setConfig(requestConfig);
			client = HttpClients.createDefault();
			response = client.execute(httpGet);
			// 获取结果
			getResponseResult(response, responseModel, clazz);
			return responseModel;
		} catch (Exception e) {
			logger.error("*******************get请求发送线程,错误信息***************", e);
			throw new ServiceRunException(ResponseEnum.EXPECTATION_FAILED.getCode(),
					ResponseEnum.EXPECTATION_FAILED.getDescription());
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (client != null) {
					client.close();
				}
			} catch (IOException e) {
				logger.error("*******************get请求发送线程,错误信息***************", e);
				throw new ServiceRunException(ResponseEnum.EXPECTATION_FAILED.getCode(),
						ResponseEnum.EXPECTATION_FAILED.getDescription());
			}
		}
	}

	/**
	 * 获取响应结果
	 * 
	 * @param response
	 * @param responseModel
	 * @param clazz
	 * @throws ParseException
	 * @throws IOException
	 */
	private static void getResponseResult(CloseableHttpResponse response, ResponseModel responseModel, Class clazz)
			throws ParseException, IOException {
		switch (response.getStatusLine().getStatusCode()) {
		case 204:
			responseModel.setCode(ResponseEnum.NO_CONTENT.getCode());
			responseModel.setMessage(ResponseEnum.NO_CONTENT.getDescription());
			break;
		case 401:
			responseModel.setCode(ResponseEnum.CUT_SYS_NOAUTH.getCode());
			responseModel.setMessage(ResponseEnum.CUT_SYS_NOAUTH.getDescription());
			break;
		case 306:
			responseModel.setCode(ResponseEnum.SWITCH_PROXY.getCode());
			responseModel.setMessage(EntityUtils.toString(response.getEntity(), "UTF-8"));
			break;
		case 200:
			String result = EntityUtils.toString(response.getEntity(), "UTF-8");
			responseModel.setData((clazz != null) ? JSONObject.parseObject(result, clazz) : result);
			responseModel.setCode(ResponseEnum.OK.getCode());
			responseModel.setMessage(ResponseEnum.OK.getDescription());
			break;
		default:
			responseModel.setCode(ResponseEnum.NO_CONTENT.getCode());
			responseModel.setMessage(EntityUtils.toString(response.getEntity(), "UTF-8"));
		}
	}

	/**
	 * post请求
	 * 
	 * @param url：请求url路径
	 * @param params：请求参数
	 * @param clazz：返回数据类型
	 * @return
	 */
	public static ResponseModel doPost(String url, Map<String, Object> params, Class clazz) {
		// 开始处理http请求信息
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		ResponseModel responseModel = new ResponseModel();
		try {
			HttpPost httpPost = new HttpPost(url);
			StringEntity entityParams = new StringEntity(JSONObject.toJSONString(params), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "application/json;charset=utf-8");
			// 设置连接超时时间，单位毫秒。
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000)
					// .setConnectionRequestTimeout(1000) 设置从connect
					// Manager获取Connection
					// 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。
					// .setSocketTimeout(5000) 请求获取数据的超时时间，单位毫秒。
					// 如果访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。
					.build();
			httpPost.setConfig(requestConfig);
			client = HttpClients.createDefault();
			response = client.execute(httpPost);
			// 获取结果
			getResponseResult(response, responseModel, clazz);
			return responseModel;
		} catch (Exception e) {
			logger.error("*******************post请求发送线程，错误信息***************", e);
			e.printStackTrace();
			throw new ServiceRunException(ResponseEnum.EXPECTATION_FAILED.getCode(),
					ResponseEnum.EXPECTATION_FAILED.getDescription());
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (client != null) {
					client.close();
				}
			} catch (IOException e) {
				logger.error("*******************post请求发送线程，错误信息***************", e);
				e.printStackTrace();
				throw new ServiceRunException(ResponseEnum.EXPECTATION_FAILED.getCode(),
						ResponseEnum.EXPECTATION_FAILED.getDescription());
			}
		}
	}
}
